package one.stand.controller;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.*;
import one.stand.config.UserVisitorsTimerConfig;
import one.stand.model.CompanyAccountModel;
import one.stand.model.CompanyModel;
import one.stand.model.live.WxShareDynamicModel;
import one.stand.request.*;
import one.stand.request.wx.*;
import one.stand.response.wx.AuthSnsapiUserinfoResponse;
import one.stand.service.CompanyAccontService;
import one.stand.service.impl.WxMessageServiceImpl;
import one.stand.util.DateUtil;
import one.stand.util.HttpUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import one.stand.model.ResultModel;
import one.stand.request.ComponentProgramRequest;
import one.stand.request.ComponentVerifyTicketRequest;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author: QIK
 * @CreateDate: 2019/5/9 14:41
 */
@RestController
@RequestMapping("wx")
@Slf4j
public class WxController extends BaseController {

    @Value("${templateHtml}")
    private String templateHtml;

    @Value("${appId}")
    private String appId;

    @Autowired
    private WxMessageServiceImpl wxMessageService;

    @Autowired
    private CompanyAccontService companyAccontService;

    @PostMapping("wxcallback")
    public String wxcallback(@RequestBody ComponentVerifyTicketRequest request) {
        return wxService.wxcallback(request);
    }

    @PostMapping("program")
    public String program(@RequestBody ComponentProgramRequest request) {
        return wxService.wxcallback(request);
    }

    @GetMapping("subscribe-templates")
    public ResultModel<Map<String, String>> subscribeTemplates(@RequestParam("companyKey") String companyKey, @RequestParam("accountType") String accountType) {
        return new ResultModel(componentService.getSubscribeTemplates(companyKey, accountType));
    }

    /**
     * 公众号授权回调
     * @return
     */
    @GetMapping("wxAuth")
    public AuthSnsapiUserinfoResponse wxAuth(@RequestParam("code") String code, @RequestParam("state") String state) {
        log.info("wxAuth:{}",code);

        AuthSnsapiUserinfoRequest authSnsapiUserinfoRequest = new AuthSnsapiUserinfoRequest();
        authSnsapiUserinfoRequest.setCode(code);
        authSnsapiUserinfoRequest.setState(state);

        return wxService.wxAuth(authSnsapiUserinfoRequest);
    }

    /**
     * 微信绑定认证
     * @param request
     * @return
     */
    @PostMapping("msgAuthGet")
    public String authGet(@RequestBody WxAuthRequest request) {
        log.info("接收到来自微信服务器的认证消息：{}", request);
        if (StringUtils.isAnyBlank(request.getSignature(), request.getTimestamp(), request.getNonce(), request.getEchostr())) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        return request.getEchostr();
    }

    /**
     *  微信消息
     *     <xml>
     *             <ToUserName><![CDATA[gh_4f43334dcccf]]></ToUserName>
     *             <FromUserName><![CDATA[oOpa_0R2qgrODzt1b20w0UwzyHqU]]></FromUserName>
     *             <CreateTime>1591339895</CreateTime>
     *             <MsgType><![CDATA[text]]></MsgType>
     *             <Content><![CDATA[1]]></Content>
     *             <MsgId>22782511910692897</MsgId>
     *          </xml>
     * @param request
     * @return
     */
    @PostMapping("msgPost")
    public String post(@RequestBody WxMsgRequest request) {
        log.info("接收微信请求：{}  ",   request);

        String out = null;
        // 明文传输的消息
        WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getRequestBody());
        log.info("inMessage:{}",inMessage);
        WxMpXmlOutMessage outMessage = null;
        if(inMessage.getContent().equals("1")){
            outMessage = this.route(inMessage.getToUser(),inMessage.getFromUser());
        }else{
            outMessage = this.routeDefault(inMessage.getToUser(),inMessage.getFromUser());
        }

        out = outMessage.toXml();
        this.wxService.sendSmMsg(inMessage.getFromUser(),request.getAppid(),inMessage.getContent());

        log.info("组装回复信息：{}", out);

        return out;
    }

    @PostMapping("updateShareNum")
    public String updateShareNum(@RequestBody ShareDynamicRequest request) {
        log.info("分享成功请求：{}  ",   request);
        return wxService.updateShareNum(request);
    }

    @PostMapping("userOpenDynamic")
    public String userOpenDynamic(@RequestBody UserTimerModel request) {
        //检查是否存在 如果存在则只更新心跳时间
        if(!UserVisitorsTimerConfig.visitors.containsKey(request.getOpenId())){
            final LocalDateTime local = LocalDateTime.now();
            request.setStartTime(local);
            request.setVisitorTime(local);
            log.info("用户进入页面：{}  ",   request);
            UserVisitorsTimerConfig.visitors.put(request.getOpenId(),request);
            //进入就算浏览一次
            wxService.updateSeeNum(request.getDynamicId());
        }else{
            UserTimerModel userTimerModel = UserVisitorsTimerConfig.visitors.get(request.getOpenId());
            if(userTimerModel != null){
                userTimerModel.setVisitorTime(LocalDateTime.now());
            }
        }

        return "0";
    }




    /**
     * 发送小程序消息
     * {
     *   "touser": "OPENID",
     *   "msgtype": "link",
     *   "link": {
     *     "title": "Happy Day",
     *     "description": "Is Really A Happy Day",
     *     "url": "URL",
     *     "thumb_url": "THUMB_URL"
     *   }
     * }
     * appId为小程序appid=appIdSm
     */
//    @Async
//    void sendSmMsg(String openId,String appIdSm,String content){
//
//        CompanyAccountModel companyAccountModel = this.companyAccontService.selectByCompanyKey(new CompanyAccountRequest() {{
//            setAppId(appIdSm);
//        }});
//        log.info("companyAccountModel:{}",companyAccountModel);
//
//        //获取公司token
//        final String token = this.wxMessageService.getWxToken(appIdSm,companyAccountModel.getAppSecret());
//
//        JSONObject msg = new JSONObject();
//        msg.put("touser",openId);
//        msg.put("msgtype",content.equals("1") ? "link" : "text");
//        JSONObject link = new JSONObject();
//
//        WxShareDynamicModel wxShareDynamicModel = this.wxService.queryUserShareDynamic(openId);
//        if(wxShareDynamicModel != null){
//            link.put("title",wxShareDynamicModel.getTitle());
//            link.put("description",wxShareDynamicModel.getOriginAuthor());
//            //
//            String url = templateHtml + String.format("?dynamicId=%s&userId=%s&appid=%s",wxShareDynamicModel.getDynamicId(),wxShareDynamicModel.getUserId(),appId);
//            link.put("url",wxShareDynamicModel.getUrl() == null ? url : wxShareDynamicModel.getUrl());
//
//            //拆分图片。保存时拼接
//            if(wxShareDynamicModel.getPhotos().contains(",")){
//                link.put("thumb_url",wxShareDynamicModel.getPhotos().split(",")[0]);
//            }else{
//                link.put("thumb_url",wxShareDynamicModel.getPhotos());
//            }
//        }
//        if(content.equals("1")){
//            msg.put("link",link);
//        }else{
//            JSONObject text = new JSONObject();
//            text.put("content","欢迎咨询壹脉名片!");
//            msg.put("text",text);
//        }
//
//        log.info("requestUrlParam:{}",msg);
//        String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token;
//        String result = HttpUtil.sendPostJson(url,msg);
//        log.info("sendmsg:{}",result);
//    }

    /**
     * 公众号 或小程序消息
     * @param fromUserName
     * @param toUserName
     * @return
     */
    private WxMpXmlOutMessage route(String fromUserName,String toUserName) {
        try {
            WxMpXmlOutNewsMessage outMessage = new WxMpXmlOutNewsMessage();
            //接收方帐号（收到的OpenID）
            outMessage.setToUserName(toUserName);
            outMessage.setFromUserName(fromUserName);
            outMessage.setCreateTime(DateUtil.now().getTime());
            //公众号 news 小程序  link
            outMessage.setMsgType("link");
            outMessage.setArticleCount(1);
            //使用openid去查询用户 toUserName = openid
            WxShareDynamicModel wxShareDynamicModel = this.wxService.queryUserShareDynamic(toUserName);
            if(wxShareDynamicModel != null){
                WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
                item.setTitle(wxShareDynamicModel.getTitle());
                item.setDescription(wxShareDynamicModel.getOriginAuthor());
                if(wxShareDynamicModel.getPhotos().contains(",")){
                    item.setPicUrl(wxShareDynamicModel.getPhotos().split(",")[0]);
                }else{
                    item.setPicUrl(wxShareDynamicModel.getPhotos());
                }

                CompanyAccountModel companyModel = this.companyAccontService.selectByCompanyKey(new CompanyAccountRequest(){{setCompanyId(wxShareDynamicModel.getCompanyId().intValue());}});
                if(companyModel != null){
                    String url = templateHtml + String.format("?dynamicId=%s&userId=%s&appid=",wxShareDynamicModel.getDynamicId(),wxShareDynamicModel.getUserId(),companyModel.getAppId());
                    item.setUrl(wxShareDynamicModel.getUrl() == null ? url : wxShareDynamicModel.getUrl());
                }
                outMessage.addArticle(item);
            }
            return outMessage;
        } catch (Exception e) {
            log.error("路由消息时出现异常！", e);
        }
        return null;
    }

    /**
     * 默认消息
     * @param fromUserName
     * @param toUserName
     * @return
     */
    private WxMpXmlOutMessage routeDefault(String fromUserName,String toUserName) {
        try {
            WxMpXmlOutTextMessage outMessage = new WxMpXmlOutTextMessage();
            //接收方帐号（收到的OpenID）
            outMessage.setToUserName(toUserName);
            //发送方的openid
            outMessage.setFromUserName(fromUserName);
            outMessage.setCreateTime(DateUtil.now().getTime());
            outMessage.setMsgType("text");
            outMessage.setContent("欢迎咨询壹脉名片!");
            return outMessage;
        } catch (Exception e) {
            log.error("路由消息时出现异常！", e);
        }
        return null;
    }


    /**
     * 获取微信jssdk签名
     * @param request
     * @return
     */
    @PostMapping("getWxJsapiSignature")
    public ResultModel getWxJsapiSignature(@RequestBody WxMsgRequest request){
        String jsapi_ticket = getTicket(request);
        //requestBody 分享的url
        Map<String, String> wsJssdk = sign(jsapi_ticket,request.getRequestBody());

        wsJssdk.put("appId",request.getAppid());
        log.info("getWxJsapiSignature:{},{}",request,wsJssdk);
        return ResultModel.success(wsJssdk);
    }

    /**
     * 获取ticket
     * @param request
     * @return
     */
    private String getTicket( WxMsgRequest request){
        return wxService.getTicketToken(request);
    }



    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        System.out.println(string1);

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}
